package bb.lanxing.mvp.presetner;

import android.content.DialogInterface;
import com.alibaba.fastjson.JSON;
import bb.lanxing.App;
import bb.lanxing.R;
import bb.lanxing.calc.PaceHelper;
import bb.lanxing.model.WorkoutDatabaseHelper;
import bb.lanxing.model.database.IWorkout;
import bb.lanxing.model.database.PacePoint;
import bb.lanxing.model.database.Trackpoint;
import bb.lanxing.model.database.Workout;
import bb.lanxing.model.json.WorkoutMergeInfo;
import bb.lanxing.mvp.model.HistoryModelImpl;
import bb.lanxing.mvp.model.WorkoutMergeModelImpl;
import bb.lanxing.mvp.model.i.IHistoryModel;
import bb.lanxing.mvp.model.i.IWorkoutMergeModel;
import bb.lanxing.mvp.presetner.i.IWorkoutMergePreviewPresenter;
import bb.lanxing.mvp.view.IWorkoutMergePreviewView;
import bb.lanxing.util.WorkoutTitleUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

public class WorkoutMergePreviewPresenterImpl extends BasePresenter implements IWorkoutMergePreviewPresenter {
    private boolean cancelMerge;
    private IWorkoutMergePreviewView mergePreviewView;
    private Subscription mergeSubscription;
    private Workout mergeWorkout;
    private IWorkoutMergeModel mergeModel = new WorkoutMergeModelImpl();
    private IHistoryModel model = new HistoryModelImpl();

    @Override
    public boolean checkPermission() {
        return true;
    }

    public WorkoutMergePreviewPresenterImpl(IWorkoutMergePreviewView vPreviewView) {
        this.mergePreviewView = vPreviewView;
    }

    @Override
    public void loadWorkout(Long[] workoutIds) {
        final Subscription subscribe = this.mergeModel.queryWorkout(workoutIds)
                .observeOn(AndroidSchedulers.mainThread()).subscribe((Subscriber<? super Workout>) new Subscriber<Workout>() {
            ArrayList<Workout> list = new ArrayList<>();

            @Override
            public void onCompleted() {
                mergePreviewView.dismissLoadingDialog();
                mergePreviewView.onWorkoutLoaded(this.list);
            }

            @Override
            public void onError(Throwable e) {
                mergePreviewView.dismissLoadingDialog();
                e.printStackTrace();
            }

            @Override
            public void onNext(Workout workout) {
                this.list.add(workout);
            }
        });
        addSubscription(subscribe);
        this.mergePreviewView.showLoadingDialog(R.string.dialog_loading, new DialogInterface.OnCancelListener() {

            @Override
            public void onCancel(DialogInterface dialog) {
                cancelSubscription(subscribe);
            }
        });
    }

    @Override
    public void mergeWorkout(List<Workout> workouts) {
        if (workouts == null || workouts.isEmpty()) {
            return;
        }
        this.cancelMerge = false;
        Subscription subscribe = Observable.just(workouts).subscribeOn(Schedulers.io()).flatMap(new Func1<List<Workout>, Observable<Workout>>() {
            
            @Override
            public Observable<Workout> call(List<Workout> workouts2) {
                ArrayList<Workout> arrayList = new ArrayList<>(workouts2.size());
                for (Workout workout : workouts2) {
                    arrayList.add(WorkoutDatabaseHelper.queryWorkoutById(workout.getId()));
                }
                return Observable.just(merge(arrayList));
            }
        }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<>() {
            @Override
            public void onCompleted() {
            }

            @Override
            public void onError(Throwable e) {
                e.printStackTrace();
                mergePreviewView.dismissLoadingDialog();
            }

            @Override
            public void onNext(Workout workout) {
                if (!cancelMerge) {
                    mergePreviewView.onMergeFinished(workout);
                } else {
                    cancelMerge();
                }
            }
        });
        this.mergeSubscription = subscribe;
        addSubscription(subscribe);
        this.mergePreviewView.onStartMerge();
    }

    public Workout merge(List<Workout> toBeMerged) {
        PaceHelper paceHelper;
        PaceHelper paceHelper2;
//        List<Workout> toBeMerged = workouts;
        int index_toMerge = 0;
        Workout workout = toBeMerged.get(0);
        Workout newWorkout = new Workout();
        newWorkout.setUuid(UUID.randomUUID().toString());
        newWorkout.setCategory(IWorkout.CATEGORY_MERGE);
        newWorkout.setUserId(workout.getUserId());
        newWorkout.setSport(workout.getSport());
        newWorkout.setLocSource(Workout.LOCATION_SOURCE_NONE);
        newWorkout.setCadenceSource(workout.getCadenceSource());
        newWorkout.setHeartSource(workout.getHeartSource());
        newWorkout.setPowerSource(workout.getPowerSource());
        newWorkout.setWorkStatus(Workout.STATUS_STOPED);
        newWorkout.setStartTime(workout.getStartTime());

        long startTime = workout.getStartTime();
        long endTime = workout.getEndTime();
        newWorkout.setTitle(WorkoutTitleUtil.buildDefaultTitlePrefix(this.mergePreviewView.getActivity(), startTime) + App.getContext().getString(R.string.workout_merge_type));
        WorkoutDatabaseHelper.save(newWorkout);
        this.mergeWorkout = newWorkout;
        PaceHelper paceHelper3 = new PaceHelper();
        int size = toBeMerged.size();
        ArrayList<WorkoutMergeInfo> arrayList = new ArrayList<>();
        long maxEndTime = endTime;
        long minStartTime = startTime;
        int trackPointIndex = 0;
        int paceIndex = 0;
        while (index_toMerge < size) {
            if (this.cancelMerge) {
                return newWorkout;
            }
            this.mergePreviewView.onMergeProgress(index_toMerge, size);
            Workout workoutToMerge = toBeMerged.get(index_toMerge);
            if (workoutToMerge != null) {
                WorkoutMergeInfo workoutMergeInfo = new WorkoutMergeInfo();
                workoutMergeInfo.setServerId(workoutToMerge.getServerId());
                workoutMergeInfo.setDistance(workoutToMerge.getDistance());
                workoutMergeInfo.setDuration(workoutToMerge.getDuration());
                workoutMergeInfo.setTitle(workoutToMerge.getTitle());
                workoutMergeInfo.setUuid(workoutToMerge.getUuid());
                workoutMergeInfo.setTrackStart(trackPointIndex);
                workoutMergeInfo.setPaceStart(paceIndex);
                workoutMergeInfo.setStartTime(workoutToMerge.getStartTime());
                workoutMergeInfo.setEndTime(workoutToMerge.getEndTime());
                newWorkout.addDistance(workoutToMerge.getDistance());
                newWorkout.addUpDistance(workoutToMerge.getUpDistance());
                newWorkout.addDownDistance(workoutToMerge.getDownDistance());
                newWorkout.addFlatDistance(workoutToMerge.getFlatDistance());
                newWorkout.addDuration(workoutToMerge.getDuration());
                newWorkout.addUpDuration(workoutToMerge.getUpDuration());
                newWorkout.addDownDuration(workoutToMerge.getDownDuration());
                newWorkout.addFlatDuration(workoutToMerge.getFlatDuration());
                if (workoutToMerge.getStartTime() < minStartTime) {
                    minStartTime = workoutToMerge.getStartTime();
                }
                if (workoutToMerge.getEndTime() > maxEndTime) {
                    maxEndTime = workoutToMerge.getEndTime();
                }

                newWorkout.setMaxSpeed(Math.max(newWorkout.getMaxSpeed(), workoutToMerge.getMaxSpeed()));
                newWorkout.setMaxCadence(Math.max(newWorkout.getMaxCadence(), workoutToMerge.getMaxCadence()));
                newWorkout.setMaxHeartrate(Math.max(newWorkout.getMaxHeartrate(), workoutToMerge.getMaxHeartrate()));
                newWorkout.setMaxPower(Math.max(newWorkout.getMaxPower(), workoutToMerge.getMaxPower()));
                newWorkout.setMaxGrade(Math.max(newWorkout.getMaxGrade(), workoutToMerge.getMaxGrade()));
                newWorkout.addCalorie(workoutToMerge.getCalorie());
                newWorkout.setMinGrade(Math.min(newWorkout.getMinGrade(), workoutToMerge.getMinGrade()));
                newWorkout.addElevationGain(workoutToMerge.getElevationGain());
                newWorkout.addElevationLoss(workoutToMerge.getElevationLoss());
                newWorkout.setAvgSpeed(newWorkout.getAvgSpeed() + workoutToMerge.getAvgSpeed());
                newWorkout.setAvgCadence(newWorkout.getAvgCadence() + workoutToMerge.getAvgCadence());
                newWorkout.setAvgHeartrate(newWorkout.getAvgHeartrate() + workoutToMerge.getAvgHeartrate());
                newWorkout.setAvgPower(newWorkout.getAvgPower() + workoutToMerge.getAvgPower());
                newWorkout.setStep(newWorkout.getStep() + workoutToMerge.getStep());
                if (this.cancelMerge) {
                    return newWorkout;
                }
                List<Trackpoint> queryTrackPointSample = WorkoutDatabaseHelper.
                        queryTrackPointSample(workoutToMerge.getId(), workoutToMerge.getLocSource(), 10000);
//                Long l = null;
                for (Trackpoint trackpoint : queryTrackPointSample) {
//                        trackpoint.setId(l);
                    trackpoint.setWorkoutId(newWorkout.getId());
                }
                paceHelper = paceHelper3;
                if (this.cancelMerge) {
                    return newWorkout;
                }
                WorkoutDatabaseHelper.saveTrackPoints(queryTrackPointSample);
                trackPointIndex += queryTrackPointSample.size();
                workoutMergeInfo.setTrackEnd(trackPointIndex);

                if (this.cancelMerge) {
                    return newWorkout;
                }
                paceHelper2 = paceHelper;
                paceHelper2.init(workoutToMerge);
                List<PacePoint> querySimplePacePoint = WorkoutDatabaseHelper
                        .querySimplePacePoint(workoutToMerge.getUuid(), 10000);
                if (querySimplePacePoint != null) {
                    for (PacePoint pacePoint : querySimplePacePoint) {
                        pacePoint.setId(null);
                        pacePoint.setWorkoutUuid(newWorkout.getUuid());
                    }
                    if (this.cancelMerge) {
                        return newWorkout;
                    }
                    WorkoutDatabaseHelper.savePacePoints(querySimplePacePoint);
                    paceIndex += querySimplePacePoint.size();
                    workoutMergeInfo.setPaceEnd(paceIndex);
                } else {
                    workoutMergeInfo.setPaceEnd(paceIndex);
                }
                paceHelper2.release();
                arrayList.add(workoutMergeInfo);
            }
            index_toMerge ++;
        }
        newWorkout.setStartTime(minStartTime);
        newWorkout.setEndTime(maxEndTime);
        newWorkout.setAvgSpeed(newWorkout.getAvgSpeed() / size);
        newWorkout.setAvgCadence(newWorkout.getAvgCadence() / size);
        newWorkout.setAvgHeartrate(newWorkout.getAvgHeartrate() / size);
        newWorkout.setAvgPower(newWorkout.getAvgPower() / size);
        newWorkout.setMergeRecord(JSON.toJSONString(arrayList));
        if (!this.cancelMerge) {
            WorkoutDatabaseHelper.save(newWorkout);
        }
        return newWorkout;
    }

    @Override
    public void cancelMerge() {
        if (this.cancelMerge) {
            return;
        }
        Subscription subscription = this.mergeSubscription;
        if (subscription != null) {
            cancelSubscription(subscription);
        }
        Workout workout = this.mergeWorkout;
        if (workout != null) {
            Observable.just(workout).subscribeOn(Schedulers.io()).flatMap(new Func1<Workout, Observable<Boolean>>() {

                @Override
                public Observable<Boolean> call(Workout workout2) {
                    WorkoutDatabaseHelper.deleteTrackPoint("WORKOUT_ID=?", new String[]{String.valueOf(mergeWorkout.getId())});
                    WorkoutDatabaseHelper.deletePacePoint("WORKOUT_UUID=?", new String[]{mergeWorkout.getUuid()});
                    WorkoutDatabaseHelper.delete(mergeWorkout);
                    return Observable.just(true);
                }
            }).observeOn(AndroidSchedulers.mainThread()).subscribe(new Action1<Boolean>() {

                @Override
                public void call(Boolean succeed) {
                    if (succeed) {
                        mergeWorkout = null;
                        cancelMerge = true;
                    }
                    mergePreviewView.onMergeCanceled();
                    mergePreviewView.dismissLoadingDialog();
                }
            });
            this.mergePreviewView.showLoadingDialog(R.string.workout_merge_cancel_progressing, false);
        }
    }
}
